package com.bp.hearthealth.pulse.lnapps.bp_ui.bp_activity.bp_blood_pressure

import android.os.CountDownTimer
import androidx.databinding.ObservableField
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.liveData
import androidx.lifecycle.switchMap
import androidx.lifecycle.viewModelScope
import com.bp.hearthealth.pulse.lnapps.R
import com.bp.hearthealth.pulse.lnapps.ads.model.AdsSwitch
import com.bp.hearthealth.pulse.lnapps.base.BpBaseViewModel
import com.bp.hearthealth.pulse.lnapps.bp_db.bp_bloodpressure.BloodPressure
import com.bp.hearthealth.pulse.lnapps.bp_db.bp_bloodpressure.BloodPressureData
import com.bp.hearthealth.pulse.lnapps.bp_extension.LogUtil
import com.bp.hearthealth.pulse.lnapps.bp_utils.Constants
import com.bp.hearthealth.pulse.lnapps.bp_utils.DateUtils
import com.bp.hearthealth.pulse.lnapps.bp_utils.RandomStringUtil
import com.hjq.toast.Toaster
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.util.UUID

class BpBloodPressureViewModel(private val repository: BpBloodPressureRepository) :
    BpBaseViewModel() {

    val systolic = ObservableField<String>("120")
    val diastolic = ObservableField<String>("80")
    val pulse = ObservableField<String>("75")
    val note = ObservableField<String>("")
    val enumStatus = MutableLiveData<Int>()
    val dataRequestParam = MutableLiveData<DataRequestParam>()
    val unLocked = ObservableField(false)
    private val unLockedId = MutableLiveData<String>()

    var saveTimeMillis = MutableLiveData<Long>()

    var cacheDateStr = MutableLiveData<String>()
    var cacheTimeStr = MutableLiveData<String>()

    var showDate = MutableLiveData<String>()
    var showTime = MutableLiveData<String>()

    fun initDate() {
        refreshSysAndDia()
        saveTimeMillis.value = System.currentTimeMillis()
        showDate.value =
            DateUtils.timestampToDate(saveTimeMillis.value!!.toLong(), Constants.TIME_STYLE)
        showTime.value = DateUtils.getCurrentTime()

        cacheDateStr.value = DateUtils.getCurrentDate()
        cacheTimeStr.value = DateUtils.getCurrentTime()
    }

    fun refreshSysAndDia() {
        if (systolic.get().toString().isEmpty() || diastolic.get().toString().isEmpty()) {
            return
        }
        val sys = systolic.get()!!.toInt()
        val dia = diastolic.get()!!.toInt()
        val pressureStatus = BpBloodPressureStatus.getBloodPressureStateOrColor(0, sys, dia)
//        LogUtil.i("当前值为：${sys}   $dia")
//        LogUtil.i("当前状态为：${pressureStatus}")
        enumStatus.value = pressureStatus
    }


    private var insertBloodPressure = MutableLiveData<BloodPressureRequestParam>()

    fun insertBloodPressure(
        userId: String,
        date: Long,
        timePeriod: Long,
        systolic: String,
        diastolic: String,
        pulse: String,
        degree: Int
    ) {
        if (systolic.isEmpty()) {
            this.systolic.set("120")
        } else {
            this.systolic.set(systolic)
        }
        if (diastolic.isEmpty()) {
            this.diastolic.set("80")
        } else {
            this.diastolic.set(diastolic)
        }
        if (pulse.isEmpty()) {
            this.pulse.set("75")
        } else {
            this.pulse.set(pulse)
        }

        if (this.systolic.get()!!.toInt() !in 20..220 || this.diastolic.get()!!
                .toInt() !in 20..220 || this.pulse.get()!!
                .toInt() !in 20..220
        ) {
            Toaster.show(R.string._enter_data_within_the_range_str)
            return
        }

        if (this.systolic.get()!!.toInt() < this.diastolic.get()!!.toInt()) {
            Toaster.show(R.string._systolic_greater_diastolic_str)
            return
        }
        insertBloodPressure.value = BloodPressureRequestParam(
            userId, date, timePeriod, systolic, diastolic, pulse, degree
        )
    }

    inner class BloodPressureRequestParam(
        val userId: String,
        val date: Long,
        val timePeriod: Long,
        val systolic: String,
        val diastolic: String,
        val pulse: String,
        val degree: Int
    )

    val insertBloodPressureResult = insertBloodPressure.switchMap { requestParam ->
        LogUtil.i("保存的时间为：${requestParam.date}")
        liveData {
            val result = try {
                // 查询特定日期下的血压数据
                val bloodPressure = repository.getBloodPressureByDate(
                    requestParam.userId, requestParam.date
                )
                val id = UUID.randomUUID().toString() + RandomStringUtil.generateRandomString(16)
                // 创建新的血压数据对象，并为其设置日期
                val newBloodPressureData = BloodPressureData(
                    id = id,
                    timePeriod = requestParam.timePeriod,
                    note = note.get().toString(),
                    systolic = systolic.get()!!.toDouble(),
                    diastolic = diastolic.get()!!.toDouble(),
                    pulse = pulse.get()!!.toDouble(),
                    degree = requestParam.degree,
                    userId = requestParam.userId,
                    date = requestParam.date,//存储当前天的时间格式yyyyMMdd
                    stateType = BpBloodPressureStatus.getBloodPressureStateOrColor(
                        0, systolic.get()!!.toInt(), diastolic.get()!!.toInt()
                    )
                )

                val newBloodPressure = if (bloodPressure.isNullOrEmpty()) {
                    // 如果特定日期下没有血压数据，则创建新的 BloodPressure 对象，并将新的血压数据添加到列表中
                    BloodPressure(
                        userId = requestParam.userId,
                        date = requestParam.date,//存储当前天的时间格式yyyyMMdd
                        timeStamp = requestParam.timePeriod,//选中日期与时间的时间戳
                        bloodPressureList = listOf(newBloodPressureData),

                        )
                } else {
                    // 如果特定日期下已存在血压数据，则将新的血压数据添加到列表中
                    val existingBloodPressure = bloodPressure[0]
                    val existingList = existingBloodPressure.bloodPressureList.toMutableList()
                    existingList.add(newBloodPressureData)
                    existingBloodPressure.copy(bloodPressureList = existingList)
                }

                val response = repository.insertBloodPressureWithPressureData(newBloodPressure)
                if (response > 0) {
                    Result.success(id)
                } else {
                    Result.success(response.toString())
                }
            } catch (e: Exception) {
                Result.failure(e)
            }
            emit(result)
        }
    }

    var bloodPressureDataInfo = MutableLiveData<BloodPressureData?>()
    fun getBloodPressureDataByPid(pid: String) {
        viewModelScope.launch(Dispatchers.Main) {
            bloodPressureDataInfo.value = repository.getBloodPressureDataBypid(pid)
        }
    }

    //指定date下的List<BloodPressureData>
    fun getBloodPressureByUserId(userId: String, date: Long) {
        dataRequestParam.value = DataRequestParam(userId, date)
    }

    class DataRequestParam(val userId: String, val date: Long)

    val bloodPressureData = dataRequestParam.switchMap {
        liveData {
            val result = try {
                val code = repository.getBloodPressureDataByUserIdAndDate(
                    dataRequestParam.value!!.userId, dataRequestParam.value!!.date
                )
                Result.success(code)
            } catch (e: Exception) {
                Result.failure(e)
            }
            emit(result)
        }
    }

    /**
     * 解锁
     */
    fun unlock(id: String) {
        if (id.isNotBlank()) {
            unLockedId.value = id
        }
    }

    val unlockResult = unLockedId.switchMap {
        liveData {
            val result = try {
                val updateUnlocked = repository.updateUnlocked(it)
                Result.success(updateUnlocked)
            } catch (e: Exception) {
                Result.failure<Int>(e)
            }
            emit(result)
        }
    }

    val timerDown = MutableLiveData<Boolean>()
    var countDownTimer: CountDownTimer? = null
    val updateDate = ObservableField<String>()
    val showViewToUnlock = ObservableField(false)
    fun startTimer() {
        countDownTimer = object : CountDownTimer(AdsSwitch.getBpRvCds().toLong() * 1000, 1000) {
            override fun onTick(millisUntilFinished: Long) {
                updateDate.set("${(millisUntilFinished / 1000) + 1}s")
                timerDown.value = false
            }

            override fun onFinish() {
                //播放广告
                timerDown.value = true
                showViewToUnlock.set(true)
            }
        }
        countDownTimer?.start()
    }

    fun stopTimer() {
        showViewToUnlock.set(true)
        countDownTimer?.cancel()
    }

    override fun onCleared() {
        super.onCleared()
        countDownTimer?.cancel()
    }

    inner class RequestParam(val userId: String, val date: Long, val bpdId: String)

    private var deleteBloodPressureData = MutableLiveData<RequestParam>()
    fun delete(userId: String, date: Long, bpdId: String) {
        deleteBloodPressureData.value = RequestParam(userId, date, bpdId)
    }

    val deleteResult = deleteBloodPressureData.switchMap {
        liveData {
            val result = try {
                val code = repository.deleteBloodPressureData(
                    deleteBloodPressureData.value!!.userId,
                    deleteBloodPressureData.value!!.date,
                    deleteBloodPressureData.value!!.bpdId
                )
                LogUtil.i("查询数据：${repository.getBloodPressureByUserId(Constants.USER_ID)}")
                Result.success(code)
            } catch (e: Exception) {
                Result.failure(e)
            }
            emit(result)
        }
    }


    var dataBean = MutableLiveData<DateRequestParam>()
    val listSize = MutableLiveData(0)
    val selectedTime = MutableLiveData(
        DateUtils.timestampToDate(
            DateUtils.thirtyDaysAgoStartTimestamp(), Constants.TIME_STYLE
        ) + "-" + DateUtils.timestampToDate(
            System.currentTimeMillis(), Constants.TIME_STYLE
        )
    )

    //默认查进30天的数据
    val startTime = MutableLiveData(DateUtils.thirtyDaysAgoStartTimestamp())
    val endTime = MutableLiveData(DateUtils.getStartAndEndOfTodayTimestamps().second)

    class DateRequestParam(val userId: String, val startTime: Long, val endTime: Long)

    fun getBloodPressureDataForDateRange(userId: String) {
        dataBean.value = DateRequestParam(userId, startTime.value!!, endTime.value!!)
        LogUtil.i("startTime: ${dataBean.value!!.startTime}  --  endTime: ${dataBean.value!!.endTime}")
    }

    val queueBloodPressureData = dataBean.switchMap {
        liveData {
            val result = try {
                val code = repository.getBloodPressureForDateRange(
                    Constants.USER_ID, dataBean.value!!.startTime, dataBean.value!!.endTime
                )
                Result.success(code)
            } catch (e: Exception) {
                Result.failure(e)
            }
            emit(result)
        }
    }
}